﻿using CIS.DB;
using CIS.Web.Common;
using CIS.Web.Models;
using CIS.Web.Properties;
using ClassHmac2003;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.IO;
using System.Linq;
using System.Linq.Dynamic;
using System.Net;
using System.Threading.Tasks;
using System.Web.Mvc;
using static System.Net.Mime.MediaTypeNames;

namespace CIS.Web.Controllers
{
	[RoutePrefix("ProfileAttendenceInfo")]
	public class ProfileAttendenceInfoController : BaseDbController
	{
		public ActionResult Index()
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName);

			return View();
		}

		public async Task<JsonCamelCaseResult> GetData(int? page, int? rows, string sort, string order, ProfileAttendenceInfoModel model)
		{
			int take = rows ?? ConstValues.DefaultGridRows;
			int skip = ((page ?? 1) - 1) * take;

			var queryTemp = from a in DbContext.ProfilePaymentRecord.AsNoTracking()
					group a by a.AttendenceId into g
					select new { g.Key, g };

			var sql = from conferenceAttendenceInfo in DbContext.ConferenceAttendenceInfo.AsNoTracking()
					.Where(x => x.Creator == LoginUser.UserName)
				  join conferenceMaster in DbContext.ConferenceMaster.AsNoTracking()
				       on conferenceAttendenceInfo.ConferenceId equals conferenceMaster.ID
				  join tran in DbContext.TransferEvidenceMaster.AsNoTracking()
				       on conferenceAttendenceInfo.ID equals tran.AttendenceId into t1
				  from tran in t1.DefaultIfEmpty()
				  join record in queryTemp
				       on conferenceAttendenceInfo.ID equals record.Key into t2
				  from rec in t2.DefaultIfEmpty()
				  join conferencePaymentMaster in DbContext.ConferencePaymentMaster.AsNoTracking()
				      on conferenceAttendenceInfo.PaymentTypeId equals conferencePaymentMaster.ID into t3
				  from conferencePaymentMaster in t3.DefaultIfEmpty()
				  join sysPaymentMaster in DbContext.SysPaymentMaster.AsNoTracking()
					on conferencePaymentMaster.PayId equals sysPaymentMaster.ID into t4
				  from sysPaymentMaster in t4.DefaultIfEmpty()
				  join visaInfo in DbContext.VisaInfo.AsNoTracking()
					on conferenceAttendenceInfo.ID equals visaInfo.AttendenceId into t5
				  from visa in t5.DefaultIfEmpty()
				  select new
				  {
					  Id = conferenceAttendenceInfo.ID,
					  ConferenceId = conferenceMaster.ID,
					  ConferenceName = conferenceMaster.ConferenceName,
					  FullName = conferenceAttendenceInfo.FullName,
					  Currency = conferenceAttendenceInfo.Currency,
					  BenefitEndDate = conferenceMaster.BenefitEndDate,
					  BenefitStartDate = conferenceMaster.BenefitStartDate,
					  Discount = conferenceAttendenceInfo.Discount,
					  TotalFee = conferenceAttendenceInfo.TotalFee,
					  CreateDate = conferenceAttendenceInfo.CreateDate,

					  ConferenceNickName = conferenceMaster.ConferenceNickName,
					  HomePageUrl = conferenceMaster.HomePageUrl,
					  HasPaid = conferenceAttendenceInfo.HasPaid,
					  IsRefund = conferenceAttendenceInfo.IsRefund,
					  PayStartDate = conferenceMaster.PayStartDate,
					  PayEndDate = conferenceMaster.PayEndDate,
					  PayRecordId = rec.g,
					  PaymentTypeId = conferenceAttendenceInfo.PaymentTypeId,
					  IsInternational = conferenceMaster.IsInternational,
					  PaymentName = sysPaymentMaster.PaymentName,
					  PaymentNameEn = sysPaymentMaster.PaymentNameEn,

					  UploadUrl = tran.UploadUrl,
					  HasVisa = conferenceAttendenceInfo.HasVisa,
				  };

			if (!string.IsNullOrWhiteSpace(model.queryConferenceName))
			{
				sql = sql.Where(x => x.ConferenceName.Contains(model.queryConferenceName));
			}

			int total = await sql.CountAsync();
			if (!string.IsNullOrEmpty(sort))
			{
				sql = sql.OrderBy(sort + ConstValues.chrSpace + order).Skip(skip).Take(take);
			}
			else
			{
				sql = sql.OrderByDescending(x => x.CreateDate).Skip(skip).Take(take);
			}

			var sqlResult = await sql.ToListAsync();

			var result = sqlResult.Select(x => new
			{
				Id = x.Id,
				ConferenceId = x.ConferenceId,
				ConferenceName = x.ConferenceName,
				FullName = x.FullName == null ? string.Empty : x.FullName,
				Currency = x.Currency,
				TotalFee = x.BenefitStartDate < DateTime.Now && DateTime.Now < x.BenefitEndDate ? x.Discount.Value.ToString("N2") : x.TotalFee.Value.ToString("N2"),
				RegistrationTime = !x.IsInternational ? x.CreateDate.Value.ToString("yyyy-MM-dd") : x.CreateDate.Value.ToString("MM/dd/yyyy"),
				
				ConferenceNickName = x.ConferenceNickName,
				HomePageUrl = x.HomePageUrl,
				HasPaid = x.HasPaid,
				IsRefund = x.IsRefund,
				BeforePay = DateTime.Now < x.PayStartDate.Value,
				AfterPay = DateTime.Now > x.PayEndDate.Value,
				PayRecordId = x.PayRecordId,
				PaymentTypeId = x.PaymentTypeId,
				PaymentName = x.IsInternational ? x.PaymentNameEn : x.PaymentName,

				HasTrans = DbContext.ConferenceFunctionMaster.AsNoTracking().Any(e => e.ConferenceId == x.ConferenceId &&
							e.Status == ConstValues.Status.正常 && e.FunctionId == ConstValues.FunctionId.ConferenceTransferEvidence),
				UploadUrl = string.IsNullOrEmpty(x.UploadUrl) ? string.Empty : x.UploadUrl.Replace("~", "").Replace("\\", "/"),
				FileName = string.IsNullOrEmpty(x.UploadUrl) ? string.Empty : x.UploadUrl.Substring(x.UploadUrl.LastIndexOf("\\")),
				HasVisa = x.HasVisa,
				SendStatus = DbContext.VisaInfo.AsNoTracking().FirstOrDefault(e => e.AttendenceId == x.Id)?.SendStatus,
			});

			return JsonCamelCase(new
			{
				Total = total,
				Rows = result,
			},
			JsonRequestBehavior.AllowGet);
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		public async Task<JsonResult> Modify(ProfileAttendenceInfoModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName);

			var result = await DbContext.ConferenceAttendenceInfo
					.FirstOrDefaultAsync(x => x.ID == model.Id);

			if (result == null)
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgRecordNotExist),
						JsonRequestBehavior.AllowGet);
			}

			using (var transaction = DbContext.Database.BeginTransaction())
			{
				var conferenceInfo = await DbContext.ConferenceMaster.AsNoTracking()
						.FirstOrDefaultAsync(x => x.ID == result.ConferenceId);

				#region ConferenceAttendenceInfo
				if (result.FamilyName != model.FamilyName)
				{
					result.FamilyName = model.FamilyName;
				}
				if (result.FirstName != model.FirstName)
				{
					result.FirstName = model.FirstName;
				}
				if (result.FullName != model.FullName)
				{
					result.FullName = string.IsNullOrEmpty(model.FullName?.Trim()) ? Utility.SetFullName(model.FamilyName?.Trim(), model.FirstName?.Trim(),
								Request.Cookies["_culture"] != null && Request.Cookies["_culture"].Value == ConstValues.Language.En ?
									ConstValues.Language.En : ConstValues.Language.Cn) : model.FullName?.Trim();
				}
				if (!(string.IsNullOrEmpty(model.Gender)))
				{
					result.Gender = model.Gender == ConstValues.Gender.男 ? true : false;
				}
				if (result.Title != model.Title)
				{
					result.Title = model.Title;
				}
				if (result.Degree != model.Degree && model.Degree != 0)
				{
					result.Degree = model.Degree;
				}
				if (result.Job != model.Job)
				{
					result.Job = model.Job;
				}
				if (result.Affiliation != model.Affiliation)
				{
					result.Affiliation = model.Affiliation;
				}
				if (result.Department != model.Department)
				{
					result.Department = model.Department;
				}
				if (result.Country != model.Country)
				{
					result.Country = model.Country;
				}
				if (result.StateStr != model.State)
				{
					result.StateStr = model.State;
				}
				if (result.CityStr != model.City)
				{
					result.CityStr = model.City;
				}
				if (result.Address != model.Address)
				{
					result.Address = model.Address;
				}
				if (result.ZipCode != model.ZipCode)
				{
					result.ZipCode = model.ZipCode;
				}
				if (result.Telephone != model.Telephone)
				{
					result.Telephone = model.Telephone;
				}
				if (result.Mobile != model.Mobile)
				{
					result.Mobile = model.Mobile;
				}
				if (result.CardId != model.CardId)
				{
					result.CardId = model.CardId;
				}
				if (!result.HasPaid && result.AttendenceIdentityId != model.AttendenceIdentityId)
				{
					result.AttendenceIdentityId = model.AttendenceIdentityId;
				}
				if (result.HasInvoiced == false && !string.IsNullOrWhiteSpace(model.InvoiceTitle))
				{
					if (result.InvoiceTitle != model.InvoiceTitle)
					{
						result.InvoiceTitle = model.InvoiceTitle;
					}
					if (result.TaxNum != model.TaxNum)
					{
						result.TaxNum = model.TaxNum;
					}
					if (result.AddressAndTel != model.AddressAndTel)
					{
						result.AddressAndTel = model.AddressAndTel;
					}
					if (result.Bank != model.Bank)
					{
						result.Bank = model.Bank;
					}
					if (result.BankAccount != model.BankAccount)
					{
						result.BankAccount = model.BankAccount;
					}
				}
				if (result.InvoiceId != model.InvoiceId)
				{
					result.InvoiceId = model.InvoiceId;
				}
				if (model.FavouriteTopic != null && model.FavouriteTopic.Length > 0)
				{
					result.FavouriteTopicId = string.Join(ConstValues.strSemicolon, model.FavouriteTopic);
				}
				else
				{
					result.FavouriteTopicId = string.Empty;
				}
				if (!(string.IsNullOrEmpty(model.Customize1)) && result.Customize1 != model.Customize1)
				{
					result.Customize1 = model.Customize1.Trim();
				}
				if (!(string.IsNullOrEmpty(model.Customize2)) && result.Customize2 != model.Customize2)
				{
					result.Customize2 = model.Customize2.Trim();
				}
				if (!(string.IsNullOrEmpty(model.Customize3)) && result.Customize3 != model.Customize3)
				{
					result.Customize3 = model.Customize3.Trim();
				}
				if (!(string.IsNullOrEmpty(model.Customize4)) && result.Customize4 != model.Customize4)
				{
					result.Customize4 = model.Customize4.Trim();
				}
				if (!(string.IsNullOrEmpty(model.Customize5)) && result.Customize5 != model.Customize5)
				{
					result.Customize5 = model.Customize5.Trim();
				}
				if (!(string.IsNullOrEmpty(model.Customize6)) && result.Customize6 != model.Customize6)
				{
					result.Customize6 = model.Customize6.Trim();
				}
				if (!(string.IsNullOrEmpty(model.Customize7)) && result.Customize7 != model.Customize7)
				{
					result.Customize7 = model.Customize7.Trim();
				}
				if (!(string.IsNullOrEmpty(model.Customize8)) && result.Customize8 != model.Customize8)
				{
					result.Customize8 = model.Customize8.Trim();
				}
				if (!(string.IsNullOrEmpty(model.Customize9)) && result.Customize9 != model.Customize9)
				{
					result.Customize9 = model.Customize9.Trim();
				}
				if (!(string.IsNullOrEmpty(model.Customize10)) && result.Customize10 != model.Customize10)
				{
					result.Customize10 = model.Customize10.Trim();
				}
				if (!string.IsNullOrEmpty(model.PaymentTypeId) && result.PaymentTypeId != model.PaymentTypeId)
				{
					result.PaymentTypeId = model.PaymentTypeId;
				}
				if (!string.IsNullOrEmpty(model.Currency) && result.Currency != model.Currency)
				{
					result.Currency = model.Currency;
				}
				#endregion

				#region ProfilePaymentInfo
				if (!result.HasPaid)
				{
					var pageFee = DbContext.ProfilePaymentInfo
							.FirstOrDefault(x => x.AttendenceId == model.Id &&
								x.FeeType == ConstValues.FeeType.版面费);

					if (pageFee == null)
					{
						if (!string.IsNullOrEmpty(model.PageFeeId))
						{
							var feeMaster = DbContext.FeePageMaster.AsNoTracking()
									.FirstOrDefault(x => x.ID == model.PageFeeId);
							if (feeMaster != null && feeMaster.Price.HasValue)
							{
								var profilePaymentInfo = new ProfilePaymentInfo
								{
									ID = Utility.GetTableId(ConstValues.TableName.ProfilePaymentInfo),
									UserName = result.Creator,
									AttendenceId = model.Id,
									FeeType = ConstValues.FeeType.版面费,
									FeeId = model.PageFeeId,
									Count = 1,
									Fee = feeMaster.Price.Value,
									Discount = feeMaster.Price.Value,
									Currency = feeMaster.Currency,
									Creator = LoginUser.UserName,
									CreateIP = LoginUser.IP,
									CreateDate = DateTime.Now
								};

								DbContext.ProfilePaymentInfo.Add(profilePaymentInfo);

								result.TotalFee += feeMaster.Price.Value;
								result.Discount += feeMaster.Price.Value;
								result.Currency = feeMaster.Currency;
								result.HasPage = true;
							}
						}
					}
					else
					{
						if (pageFee.FeeId != model.PageFeeId)
						{
							result.TotalFee = result.TotalFee - pageFee.Fee;
							result.Discount = result.Discount - pageFee.Discount;
							DbContext.ProfilePaymentInfo.Remove(pageFee);

							var feeMaster = DbContext.FeePageMaster.AsNoTracking()
									.FirstOrDefault(x => x.ID == model.PageFeeId);
							if (feeMaster != null && feeMaster.Price.HasValue)
							{
								var profilePaymentInfo = new ProfilePaymentInfo
								{
									ID = Utility.GetTableId(ConstValues.TableName.ProfilePaymentInfo),
									UserName = result.Creator,
									AttendenceId = model.Id,
									FeeType = ConstValues.FeeType.版面费,
									FeeId = model.PageFeeId,
									Count = 1,
									Fee = feeMaster.Price.Value,
									Discount = feeMaster.Price.Value,
									Currency = feeMaster.Currency,
									Creator = LoginUser.UserName,
									CreateIP = LoginUser.IP,
									CreateDate = DateTime.Now
								};

								DbContext.ProfilePaymentInfo.Add(profilePaymentInfo);

								result.TotalFee += feeMaster.Price.Value;
								result.Discount += feeMaster.Price.Value;
								result.Currency = feeMaster.Currency;
								result.HasPage = true;
							}
						}
						else
						{
							result.HasPage = false;
						}
					}

					var attendenceFee = DbContext.ProfilePaymentInfo
							.FirstOrDefault(x => x.AttendenceId == model.Id &&
								x.FeeType == ConstValues.FeeType.参会费);

					if (attendenceFee == null)
					{
						if (!string.IsNullOrEmpty(model.AttendenceFeeId))
						{
							var feeMaster = DbContext.FeeAttendenceMaster.AsNoTracking()
									.FirstOrDefault(x => x.ID == model.AttendenceFeeId);
							if (feeMaster != null && feeMaster.Price.HasValue)
							{
								double originFee = feeMaster.Price.Value;
								double discountFee = feeMaster.Discount.HasValue ? feeMaster.Discount.Value : feeMaster.Price.Value;

								var profilePaymentInfo = new ProfilePaymentInfo
								{
									ID = Utility.GetTableId(ConstValues.TableName.ProfilePaymentInfo),
									UserName = result.Creator,
									AttendenceId = model.Id,
									FeeType = ConstValues.FeeType.参会费,
									FeeId = model.AttendenceFeeId,
									Count = 1,
									Fee = originFee,
									Discount = discountFee,
									Currency = feeMaster.Currency,
									Creator = LoginUser.UserName,
									CreateIP = LoginUser.IP,
									CreateDate = DateTime.Now
								};

								DbContext.ProfilePaymentInfo.Add(profilePaymentInfo);

								result.TotalFee += originFee;
								result.Discount += discountFee;
								result.Currency = feeMaster.Currency;
							}
						}
					}
					else
					{
						if (attendenceFee.FeeId != model.AttendenceFeeId)
						{
							result.TotalFee = result.TotalFee - attendenceFee.Fee;
							result.Discount = result.Discount - attendenceFee.Discount;
							DbContext.ProfilePaymentInfo.Remove(attendenceFee);

							var feeMaster = DbContext.FeeAttendenceMaster.AsNoTracking()
									.FirstOrDefault(x => x.ID == model.AttendenceFeeId);
							if (feeMaster != null && feeMaster.Price.HasValue)
							{
								double originFee = feeMaster.Price.Value;
								double discountFee = feeMaster.Discount.HasValue ? feeMaster.Discount.Value : feeMaster.Price.Value;

								var profilePaymentInfo = new ProfilePaymentInfo
								{
									ID = Utility.GetTableId(ConstValues.TableName.ProfilePaymentInfo),
									UserName = result.Creator,
									AttendenceId = model.Id,
									FeeType = ConstValues.FeeType.参会费,
									FeeId = model.AttendenceFeeId,
									Count = 1,
									Fee = originFee,
									Discount = discountFee,
									Currency = feeMaster.Currency,
									Creator = LoginUser.UserName,
									CreateIP = LoginUser.IP,
									CreateDate = DateTime.Now
								};

								DbContext.ProfilePaymentInfo.Add(profilePaymentInfo);

								result.TotalFee += originFee;
								result.Discount += discountFee;
								result.Currency = feeMaster.Currency;
							}
						}
					}

					var mealFee = DbContext.ProfilePaymentInfo
							.FirstOrDefault(x => x.AttendenceId == model.Id &&
								x.FeeType == ConstValues.FeeType.餐费);

					if (mealFee == null)
					{
						if (!string.IsNullOrEmpty(model.MealFeeId))
						{
							var feeMaster = DbContext.FeeMealMaster.AsNoTracking()
									.FirstOrDefault(x => x.ID == model.MealFeeId);
							if (feeMaster != null && feeMaster.Price.HasValue)
							{
								var profilePaymentInfo = new ProfilePaymentInfo
								{
									ID = Utility.GetTableId(ConstValues.TableName.ProfilePaymentInfo),
									UserName = result.Creator,
									AttendenceId = model.Id,
									FeeType = ConstValues.FeeType.餐费,
									FeeId = model.MealFeeId,
									Count = 1,
									Fee = feeMaster.Price.Value,
									Discount = feeMaster.Price.Value,
									Currency = feeMaster.Currency,
									Creator = LoginUser.UserName,
									CreateIP = LoginUser.IP,
									CreateDate = DateTime.Now
								};

								DbContext.ProfilePaymentInfo.Add(profilePaymentInfo);

								result.TotalFee += feeMaster.Price.Value;
								result.Discount += feeMaster.Price.Value;
								result.Currency = feeMaster.Currency;
								result.HasMeal = true;
							}
						}
					}
					else
					{
						if (mealFee.FeeId != model.MealFeeId)
						{
							result.TotalFee = result.TotalFee - mealFee.Fee;
							result.Discount = result.Discount - mealFee.Discount;
							DbContext.ProfilePaymentInfo.Remove(mealFee);

							var feeMaster = DbContext.FeeMealMaster.AsNoTracking()
									.FirstOrDefault(x => x.ID == model.MealFeeId);
							if (feeMaster != null && feeMaster.Price.HasValue)
							{
								var profilePaymentInfo = new ProfilePaymentInfo
								{
									ID = Utility.GetTableId(ConstValues.TableName.ProfilePaymentInfo),
									UserName = result.Creator,
									AttendenceId = model.Id,
									FeeType = ConstValues.FeeType.餐费,
									FeeId = model.MealFeeId,
									Count = 1,
									Fee = feeMaster.Price.Value,
									Discount = feeMaster.Price.Value,
									Currency = feeMaster.Currency,
									Creator = LoginUser.UserName,
									CreateIP = LoginUser.IP,
									CreateDate = DateTime.Now
								};

								DbContext.ProfilePaymentInfo.Add(profilePaymentInfo);

								result.TotalFee += feeMaster.Price.Value;
								result.Discount += feeMaster.Price.Value;
								result.Currency = feeMaster.Currency;
								result.HasMeal = true;
							}
						}
						else
						{
							result.HasMeal = false;
						}
					}

					var eventFee = await DbContext.ProfilePaymentInfo.Where(x => x.AttendenceId == model.Id && x.FeeType == ConstValues.FeeType.同期活动费).ToListAsync();
					if (eventFee.Count > 0)
					{
						for (var i = 0; i < eventFee.Count; i++)
						{
							result.TotalFee -= eventFee[i].Fee;
							result.Discount -= eventFee[i].Fee;
						}

						DbContext.ProfilePaymentInfo.RemoveRange(eventFee);

					}
					if (!string.IsNullOrEmpty(model.HidEventIdList) && !string.IsNullOrEmpty(model.HidCountList))
					{
						var concurrentEventList = model.HidEventIdList.Split(ConstValues.chrComma);
						var concurrentEventCount = model.HidCountList.Split(ConstValues.chrComma);
						for (var index = 0; index < concurrentEventList.Length; index++)
						{
							string tmp = concurrentEventList[index];
							int count = int.Parse(concurrentEventCount[index]);

							var feeMaster = DbContext.FeeConcurrentEventMaster.AsNoTracking().FirstOrDefault(x => x.ConcurrentEventId == tmp && x.Status == ConstValues.Status.正常
										&& (x.AttendenceIdentityId == model.AttendenceIdentityId || x.AttendenceIdentityId == ConstValues.ApplicableForAll)
										&& x.Currency == model.Currency);

							if (feeMaster != null && count != 0)
							{
								var profilePaymentInfo = new ProfilePaymentInfo
								{
									ID = Utility.GetTableId(ConstValues.TableName.ProfilePaymentInfo),
									UserName = result.Creator,
									AttendenceId = model.Id,
									FeeType = ConstValues.FeeType.同期活动费,
									FeeId = feeMaster.ID,
									Count = count,
									Fee = feeMaster.Price.Value * count,
									Discount = feeMaster.Price.Value * count,
									Currency = feeMaster.Currency,
									Creator = LoginUser.UserName,
									CreateIP = LoginUser.IP,
									CreateDate = DateTime.Now
								};

								DbContext.ProfilePaymentInfo.Add(profilePaymentInfo);

								result.TotalFee += feeMaster.Price.Value * count;
								result.Discount += feeMaster.Price.Value * count;
								result.Currency = feeMaster.Currency;
							}
						}
					}
				}
				#endregion

				result.Sort = model.Sort.HasValue ? model.Sort.Value : ConstValues.DefaultSort;
				result.Remark = model.Remark?.Trim();
				result.Updater = LoginUser.UserName;
				result.UpdateIP = LoginUser.IP;
				result.UpdateDate = DateTime.Now;

				Utility.SaveInvoiceInfo(LoginUser, new InvoiceModel
				{
					InvoiceTitle = model.InvoiceTitle,
					TaxNum = model.TaxNum,
					AddressAndTel = model.AddressAndTel,
					Bank = model.Bank,
					BankAccount = model.BankAccount,
				});

				await DbContext.SaveChangesAsync();
				transaction.Commit();
			}

			return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessSubmit),
					JsonRequestBehavior.AllowGet);
		}

		public async Task<JsonCamelCaseResult> GetOtherFeeData(string id)
		{
			var sql = DbContext.ProfilePaymentInfo.AsNoTracking()
					.Where(x => x.AttendenceId == id &&
						x.FeeType == ConstValues.FeeType.其他费用)
					.OrderBy(x => x.CreateDate)
					.Join(DbContext.FeeOtherMaster.AsNoTracking()
						.Where(x => x.Status == ConstValues.Status.正常),
					pay => pay.FeeId,
					fee => fee.ID,
					(pay, fee) => new
					{
						Id = pay.ID,
						FeeName = fee.FeeName,
						Count = pay.Count,
						UnitPrice = fee.Price,
						Currency = fee.Currency,
						Price = pay.Fee
					});

			var sqlResult = await sql.ToListAsync();

			var result = sqlResult.Select(x => new
			{
				Id = x.Id,
				FeeName = x.FeeName,
				Count = x.Count,
				UnitPrice = x.UnitPrice.Value.ToString("N2"),
				Currency = x.Currency,
				Price = x.Price.ToString("N2")
			});

			return JsonCamelCase(result, JsonRequestBehavior.AllowGet);
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		[Route("CreateOtherFee")]
		public async Task<JsonResult> CreateOtherFee(OtherFeeModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName);

			var result = await DbContext.ProfilePaymentInfo
					.FirstOrDefaultAsync(x => x.AttendenceId == model.AttendenceId &&
						x.FeeType == ConstValues.FeeType.其他费用 &&
						x.FeeId == model.OtherFeeId);

			if (result != null)
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(
						string.Format(Resources.MsgRecordExist, Resources.FeeName)),
						JsonRequestBehavior.AllowGet);
			}

			using (var transaction = DbContext.Database.BeginTransaction())
			{
				var otherFee = await DbContext.FeeOtherMaster.AsNoTracking()
						.FirstOrDefaultAsync(x => x.ID == model.OtherFeeId);

				if (otherFee != null && otherFee.Price.HasValue)
				{
					var info = await DbContext.ConferenceAttendenceInfo
							.FirstOrDefaultAsync(x => x.ID == model.AttendenceId);

					info.TotalFee = info.TotalFee + otherFee.Price.Value * model.Count.Value;
					info.Discount = info.Discount + otherFee.Price.Value * model.Count.Value;
					info.Currency = otherFee.Currency;
					info.Updater = LoginUser.UserName;
					info.UpdateIP = LoginUser.IP;
					info.UpdateDate = DateTime.Now;

					var profilePaymentInfo = new ProfilePaymentInfo
					{
						ID = Utility.GetTableId(ConstValues.TableName.ProfilePaymentInfo),
						UserName = info.Creator,
						AttendenceId = model.AttendenceId,
						FeeType = ConstValues.FeeType.其他费用,
						FeeId = model.OtherFeeId,
						Count = model.Count,
						Fee = otherFee.Price.Value * model.Count.Value,
						Discount = otherFee.Price.Value * model.Count.Value,
						Currency = otherFee.Currency,
						Creator = LoginUser.UserName,
						CreateIP = LoginUser.IP,
						CreateDate = DateTime.Now
					};

					DbContext.ProfilePaymentInfo.Add(profilePaymentInfo);
				}

				await DbContext.SaveChangesAsync();
				transaction.Commit();
			}

			return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessSubmit),
					JsonRequestBehavior.AllowGet);
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		[Route("DeleteOtherFee")]
		public async Task<JsonResult> DeleteOtherFee(OtherFeeModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName);

			var result = await DbContext.ProfilePaymentInfo
					.FirstOrDefaultAsync(x => x.ID == model.Id);

			if (result == null)
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgRecordNotExist),
						JsonRequestBehavior.AllowGet);
			}

			using (var transaction = DbContext.Database.BeginTransaction())
			{
				var info = await DbContext.ConferenceAttendenceInfo
						.FirstOrDefaultAsync(x => x.ID == model.AttendenceId);

				info.TotalFee = info.TotalFee - result.Fee;
				info.Discount = info.Discount - result.Fee;
				info.Updater = LoginUser.UserName;
				info.UpdateIP = LoginUser.IP;
				info.UpdateDate = DateTime.Now;

				DbContext.ProfilePaymentInfo.Remove(result);

				await DbContext.SaveChangesAsync();
				transaction.Commit();
			}

			return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessDelete),
					JsonRequestBehavior.AllowGet);
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		[Route("Delete/{id}")]
		public async Task<JsonResult> Delete(string id)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName);

			var result = await DbContext.ConferenceAttendenceInfo
					.FirstOrDefaultAsync(x => x.ID == id);

			if (result != null)
			{
				if (result.HasPaid)
				{
					return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgUsingCanNotDelete),
							JsonRequestBehavior.AllowGet);
				}

				using (var transaction = DbContext.Database.BeginTransaction())
				{
					DbContext.ConferenceAttendenceInfo.Remove(result);

					var profilePaymentInfoList = await DbContext.ProfilePaymentInfo
							.Where(x => x.AttendenceId == id).ToListAsync();
					DbContext.ProfilePaymentInfo.RemoveRange(profilePaymentInfoList);

					var profilePaymentRecordList = await DbContext.ProfilePaymentRecord
							.Where(x => x.AttendenceId == id).ToListAsync();
					DbContext.ProfilePaymentRecord.RemoveRange(profilePaymentRecordList);

					var conferencePayStatusInfoList = await DbContext.ConferencePayStatusInfo
							.Where(x => x.AttendenceId == id).ToListAsync();
					DbContext.ConferencePayStatusInfo.RemoveRange(conferencePayStatusInfoList);

					await DbContext.SaveChangesAsync();
					transaction.Commit();
				}

				return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessDelete),
						JsonRequestBehavior.AllowGet);
			}
			else
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgRecordNotExist),
						JsonRequestBehavior.AllowGet);
			}
		}

		[Route("GetPaymentInfoData/{id}")]
		public async Task<JsonCamelCaseResult> GetPaymentInfoData(string id)
		{
			var sql = from paymentInfo in DbContext.ProfilePaymentInfo.AsNoTracking()
					.Where(x => x.AttendenceId == id)
				  join attInfo in DbContext.ConferenceAttendenceInfo.AsNoTracking()
					on paymentInfo.AttendenceId equals attInfo.ID
				  join conferenceMaster in DbContext.ConferenceMaster.AsNoTracking()
					on attInfo.ConferenceId equals conferenceMaster.ID
				  orderby paymentInfo.FeeType
				  select new ProfilePayInfoModel
				  {
					  FeeType = paymentInfo.FeeType,
					  FeeId = paymentInfo.FeeId,
					  FeeName = string.Empty,
					  Count = paymentInfo.Count,
					  Currency = paymentInfo.Currency,
					  Fee = paymentInfo.Fee,
					  Discount = paymentInfo.Discount,
					  BenefitEndDate = conferenceMaster.BenefitEndDate,
					  BenefitStartDate = conferenceMaster.BenefitStartDate,
					  ConferenceId = conferenceMaster.ID,
					  DisplayName = ""
				  };

			int total = await sql.CountAsync();
			var sqlResult = await sql.ToListAsync();

			double? conferenceFee = 0.00;
			double? eventFee = 0.00;
			string totalCurrency = "";
			sqlResult.ForEach(x =>
			{
				if (x.FeeType == ConstValues.FeeType.餐费)
				{
					x.DisplayName = DbContext.ConferenceAttendenceForm.AsNoTracking().FirstOrDefault(y => y.ConferenceId == x.ConferenceId && y.Key == "Meal")?.DisplayName;
					double? Fee = x.BenefitStartDate < DateTime.Now && DateTime.Now < x.BenefitEndDate ? x.Discount : x.Fee;
					conferenceFee += Fee;
					x.FeeName = DbContext.FeeMealMaster.AsNoTracking().FirstOrDefault(y => y.ID == x.FeeId).FeeName;
					totalCurrency = x.Currency;
				}
				else if (x.FeeType == ConstValues.FeeType.参会费)
				{
					x.DisplayName = DbContext.ConferenceAttendenceForm.AsNoTracking().FirstOrDefault(y => y.ConferenceId == x.ConferenceId && y.Key == "Attendence")?.DisplayName;
					double? Fee = x.BenefitStartDate < DateTime.Now && DateTime.Now < x.BenefitEndDate ? x.Discount : x.Fee;
					conferenceFee += Fee;
					x.FeeName = DbContext.FeeAttendenceMaster.AsNoTracking().FirstOrDefault(y => y.ID == x.FeeId).RegisterType;
					totalCurrency = x.Currency;
				}
				else if (x.FeeType == ConstValues.FeeType.版面费)
				{
					x.DisplayName = DbContext.ConferenceAttendenceForm.AsNoTracking().FirstOrDefault(y => y.ConferenceId == x.ConferenceId && y.Key == "Page")?.DisplayName;
					double? Fee = x.BenefitStartDate < DateTime.Now && DateTime.Now < x.BenefitEndDate ? x.Discount : x.Fee;
					conferenceFee += Fee;
					x.FeeName = DbContext.FeePageMaster.AsNoTracking().FirstOrDefault(y => y.ID == x.FeeId).FeeName;
					totalCurrency = x.Currency;
				}
				else if (x.FeeType == ConstValues.FeeType.其他费用)
				{
					x.DisplayName = DbContext.ConferenceAttendenceForm.AsNoTracking().FirstOrDefault(y => y.ConferenceId == x.ConferenceId && y.Key == "Other")?.DisplayName;
					double? Fee = x.BenefitStartDate < DateTime.Now && DateTime.Now < x.BenefitEndDate ? x.Discount : x.Fee;
					conferenceFee += Fee;
					x.FeeName = DbContext.FeeOtherMaster.AsNoTracking().FirstOrDefault(y => y.ID == x.FeeId).FeeName;
					totalCurrency = x.Currency;
				}
				else if (x.FeeType == ConstValues.FeeType.同期活动费)
				{
					x.DisplayName = DbContext.ConferenceAttendenceForm.AsNoTracking().FirstOrDefault(y => y.ConferenceId == x.ConferenceId && y.Key == "ConcurrentEvent")?.DisplayName;
					var ConcurrentEventId = DbContext.FeeConcurrentEventMaster.AsNoTracking().FirstOrDefault(y => y.ID == x.FeeId)?.ConcurrentEventId;
					x.FeeName = DbContext.ConcurrentEventMaster.AsNoTracking().FirstOrDefault(y => y.ID == ConcurrentEventId)?.EventName;
					double? Fee = x.BenefitStartDate < DateTime.Now && DateTime.Now < x.BenefitEndDate ? x.Discount : x.Fee;
					eventFee += Fee;
					totalCurrency = x.Currency;
				}
			});

			var result = sqlResult.Select((x, index) => new
			{
				Number = index + 1,
				Currency = x.Currency,
				Name = x.DisplayName + ConstValues.chrSpace + ConstValues.chrComma + ConstValues.chrSpace + x.FeeName,
				Fee = x.BenefitStartDate < DateTime.Now && DateTime.Now < x.BenefitEndDate ? x.Discount : x.Fee,
			});

			return JsonCamelCase(new
			{
				Total = total,
				Rows = result,
			},
			JsonRequestBehavior.AllowGet);
		}

		[Route("GetPaymentRecord/{id}")]
		public async Task<JsonCamelCaseResult> GetPaymentRecord(string id)
		{
			var personal = await DbContext.ConferenceAttendenceInfo.AsNoTracking().FirstOrDefaultAsync(x => x.ID == id);
			var conferenceMaster = await DbContext.ConferenceMaster.AsNoTracking().FirstOrDefaultAsync(x => x.ID == personal.ConferenceId);

			var sql = DbContext.ProfilePaymentRecord.AsNoTracking()
					.Where(x => x.AttendenceId == id)
					.Select(x => new
					{
						x.Currency,
						x.Fee,
						x.CreateDate,
						FeeStatus = x.FeeStatus ? Resources.SuccessPay : Resources.FailPay,
					})
					.Union(DbContext.ConferencePayStatusInfo.AsNoTracking()
					.Where(x => x.AttendenceId == id)
					.Select(x => new
					{
						x.Currency,
						x.Fee,
						x.CreateDate,
						x.FeeStatus,
					}))
					.OrderByDescending(x => x.CreateDate);

			int total = await sql.CountAsync();
			var sqlResult = await sql.ToListAsync();

			var result = sqlResult.Select(x => new
			{
				Currency = x.Currency,
				Fee = x.Fee.ToString("N2"),
				CreateDate = conferenceMaster.IsInternational ?
						x.CreateDate.Value.ToString("MM/dd/yyyy HH:mm") :
						x.CreateDate.Value.ToString("yyyy-MM-dd HH:mm"),
				FeeStatus = x.FeeStatus == ConstValues.PaidStatus.退款 ? Resources.Refunded :
						x.FeeStatus == ConstValues.PaidStatus.已缴费 ? Resources.SuccessPay :
						x.FeeStatus == ConstValues.PaidStatus.未缴费 ? Resources.FailPay : x.FeeStatus,
			});

			return JsonCamelCase(new
			{
				Total = total,
				Rows = result,
			},
			JsonRequestBehavior.AllowGet);
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		public async Task<JsonResult> Import(ProfileAttendenceInfoModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName);

			var transferEvidenceMaster = await DbContext.TransferEvidenceMaster
					.FirstOrDefaultAsync(x => x.ConferenceId == model.ConferenceId &&
						x.AttendenceId == model.Id);

			if (model.TransferEvidenceFile != null)
			{
				if (model.TransferEvidenceFile.ContentLength > ConstValues.PicMaxLength)
				{
					string errorMessage = Resources.MsgPicOverflowError;
					return JsonCamelCase(Utility.CreateFailJsonResult(errorMessage),
						JsonRequestBehavior.AllowGet);
				}

				string nickName = DbContext.ConferenceMaster.AsNoTracking().FirstOrDefault(x => x.ID == model.ConferenceId)?.ConferenceNickName;
				string folder = Path.Combine(ConstValues.PaymentImg, nickName);
				string pfolder = Path.Combine(Server.MapPath(ConstValues.PaymentImg), nickName);

				string fileName = nickName + ConstValues.strHyphen +
						Path.GetExtension(model.TransferEvidenceFile.FileName).Replace(".", "").ToUpper() + ConstValues.strHyphen +
						DateTime.Now.ToString("yyyy") + ConstValues.strHyphen +
						Utility.GetRandom() + Path.GetExtension(model.TransferEvidenceFile.FileName);
				model.TransferEvidenceFilePath = Path.Combine(folder, fileName);
				var saveFileTask = Task.Run(() =>
				{
					string pFullPath = Path.Combine(pfolder, fileName);
					if (!Directory.Exists(pfolder))
					{
						Directory.CreateDirectory(pfolder);
					}
					model.TransferEvidenceFile.SaveAs(pFullPath);
				});
				Task.WaitAll(saveFileTask);

				using (var transaction = DbContext.Database.BeginTransaction())
				{
					if (transferEvidenceMaster == null)
					{
						transferEvidenceMaster = new TransferEvidenceMaster
						{
							ID = Utility.GetTableId(ConstValues.TableName.TransferEvidenceMaster),
							ConferenceId = model.ConferenceId,
							AttendenceId = model.Id,
							UploadUrl = model.TransferEvidenceFilePath?.Trim(),
							Remark = model.Remark?.Trim(),
							Status = ConstValues.Status.正常,
							Sort = ConstValues.DefaultSort,
							Creator = LoginUser.UserName,
							CreateIP = LoginUser.IP,
							CreateDate = DateTime.Now,
						};

						DbContext.TransferEvidenceMaster.Add(transferEvidenceMaster);
					}
					else
					{
						if (model.TransferEvidenceFile != null)
						{
							transferEvidenceMaster.UploadUrl = model.TransferEvidenceFilePath?.Trim();
							transferEvidenceMaster.Remark = model.Remark?.Trim();
							transferEvidenceMaster.Updater = LoginUser.UserName;
							transferEvidenceMaster.UpdateIP = LoginUser.IP;
							transferEvidenceMaster.UpdateDate = DateTime.Now;
						}
					}

					await DbContext.SaveChangesAsync();
					transaction.Commit();
				}

				return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessSubmit), JsonRequestBehavior.AllowGet);
			}
			else
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.FailUpload), JsonRequestBehavior.AllowGet);
			}
		}

		[Route("GetVisaInfoData/{id}")]
		public async Task<JsonCamelCaseResult> GetVisaInfoData(string id)
		{
			var result = await DbContext.VisaInfo.AsNoTracking().FirstOrDefaultAsync(x => x.AttendenceId == id);

			if (result == null)
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(string.Empty),
						JsonRequestBehavior.AllowGet);
			}

			return JsonCamelCase(Utility.CreateSuccessJsonResult(string.Empty, result),
					JsonRequestBehavior.AllowGet);
		}

		[Route("SaveVisa")]
		public async Task<JsonResult> SaveVisa(ProfileVisaModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName);

			using (var transaction = DbContext.Database.BeginTransaction())
			{
				var result = await DbContext.VisaInfo.FirstOrDefaultAsync(x => x.AttendenceId == model.AttendenceId);

				if (result == null)
				{
					var visaInfo = new VisaInfo
					{
						ID = Utility.GetTableId(ConstValues.TableName.VisaInfo),
						ConferenceId = model.ConferenceId,
						AttendenceId = model.AttendenceId,
						FamilyName = string.IsNullOrEmpty(model.FamilyName) ? string.Empty : model.FamilyName?.Trim(),
						FirstName = string.IsNullOrEmpty(model.FirstName) ? string.Empty : model.FirstName?.Trim(),
						FullName = Utility.SetFullName(model.FamilyName?.Trim(), model.FirstName?.Trim(),
								Request.Cookies["_culture"] != null && Request.Cookies["_culture"].Value == ConstValues.Language.En ?
									ConstValues.Language.En : ConstValues.Language.Cn),
						StateStr = model.State,
						Telephone = model.Telephone?.Trim(),
						Title = model.Title,
						ZipCode = model.ZipCode?.Trim(),
						Address = model.Address?.Trim(),
						CityStr = model.City,
						Country = model.Country,
						Gender = model.Gender == "Female" ? false : true,
						PassportNum = model.PassportNum,
						IssueOfCountry = model.CountryOfIssue,
						ArrivalDate = model.ArrivalDate,
						DeparturalDate = model.DeparturalDate,
						DateOfIssue = model.IssueDate,
						ExpiryDate = model.ExpiryDate,
						Mail = model.Mail,
						Affiliation = model.Affiliation,
						Remark = model.Remark,
						Birthdate = model.Birthday,
						Creator = LoginUser.UserName,
						CreateDate = DateTime.Now,
						CreateIP = LoginUser.IP,
						Status = ConstValues.InvitationStatus.已申请,
						SendStatus = ConstValues.SendStatus.未发送,
					};

					DbContext.VisaInfo.Add(visaInfo);
				}
				else
				{
					result.FamilyName = string.IsNullOrEmpty(model.FamilyName) ? string.Empty : model.FamilyName?.Trim();
					result.FirstName = string.IsNullOrEmpty(model.FirstName) ? string.Empty : model.FirstName?.Trim();
					result.Affiliation = model.Affiliation?.Trim();
					result.Mail = model.Mail?.Trim();
					result.Telephone = model.Telephone?.Trim();
					result.Title = model.Title;
					result.ZipCode = model.ZipCode?.Trim();
					result.Address = model.Address?.Trim();
					result.Birthdate = model.Birthday;
					result.CityStr = model.City;
					result.Country = model.Country;
					result.StateStr = model.State;
					result.Gender = model.Gender == "Female" ? false : true;
					result.PassportNum = model.PassportNum;
					result.IssueOfCountry = model.CountryOfIssue;
					result.DateOfIssue = model.IssueDate;
					result.ExpiryDate = model.ExpiryDate;
					result.ArrivalDate = model.ArrivalDate;
					result.DeparturalDate = model.DeparturalDate;

					result.Updater = LoginUser.UserName;
					result.UpdateDate = DateTime.Now;
					result.UpdateIP = LoginUser.IP;
				}

				var attendenceInfo = await DbContext.ConferenceAttendenceInfo.FirstOrDefaultAsync(x => x.ID == model.AttendenceId);
				attendenceInfo.HasVisa = true;
				attendenceInfo.Updater = LoginUser.UserName;
				attendenceInfo.UpdateDate = DateTime.Now;
				attendenceInfo.UpdateIP = LoginUser.IP;

				await DbContext.SaveChangesAsync();
				transaction.Commit();
			}

			return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessSubmit), JsonRequestBehavior.AllowGet);
		}

		[Route("DownloadInvitation/{id}")]
		public async Task<ActionResult> DownloadInvitation(string id)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName);

			var result = await DbContext.VisaInfo.AsNoTracking().FirstOrDefaultAsync(x => x.AttendenceId == id);

			if (result != null && !string.IsNullOrEmpty(result.Invitation))
			{
				return File(result.Invitation, Application.Octet, Path.GetFileName(result.Invitation));
			}
			else
			{
				return new HttpStatusCodeResult(HttpStatusCode.NotFound);
			}
		}

		[Route("GetInvoiceInfoData/{id}")]
		public async Task<JsonCamelCaseResult> GetInvoiceInfoData(string id)
		{
			var sqlResult = await DbContext.ConferenceAttendenceInfo.AsNoTracking()
					.FirstOrDefaultAsync(x => x.ID == id);

			if (sqlResult == null)
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(string.Empty),
						JsonRequestBehavior.AllowGet);
			}

			var result = new
			{
				HasInvoiced = sqlResult.HasInvoiced ? "已开票" : "未开票",
				InvoiceTitle = sqlResult.InvoiceTitle == null ? string.Empty : sqlResult.InvoiceTitle,
				TaxNum = sqlResult.TaxNum == null ? string.Empty : sqlResult.TaxNum,
				AddressAndTel = sqlResult.AddressAndTel == null ? string.Empty : sqlResult.AddressAndTel,
				Bank = sqlResult.Bank == null ? string.Empty : sqlResult.Bank,
				BankAccount = sqlResult.BankAccount == null ? string.Empty : sqlResult.BankAccount,
				InvoiceAddress = string.IsNullOrEmpty(sqlResult.InvoiceAddress) ? sqlResult.Address : sqlResult.InvoiceAddress,
				InvoiceReceive = string.IsNullOrEmpty(sqlResult.InvoiceReceive) ? sqlResult.FullName : sqlResult.InvoiceReceive,
				InvoiceTel = string.IsNullOrEmpty(sqlResult.InvoiceTel) ? sqlResult.Mobile : sqlResult.InvoiceTel,
				InvoiceMail = string.IsNullOrEmpty(sqlResult.InvoiceMail) ? sqlResult.Mail : sqlResult.InvoiceMail,

				InvoiceType = sqlResult.InvoiceType == null ? string.Empty : sqlResult.InvoiceType,
				InvoiceClass = sqlResult.InvoiceClass == null ? string.Empty : sqlResult.InvoiceClass,
				InvoiceDate = sqlResult.InvoiceDate == null ? string.Empty : sqlResult.InvoiceDate,
				InvoiceCode = sqlResult.InvoiceCode == null ? string.Empty : sqlResult.InvoiceCode,
				InvoiceNum = sqlResult.InvoiceNum == null ? string.Empty : sqlResult.InvoiceNum,
				InvoiceAmount = sqlResult.InvoiceAmount == null ? string.Empty : sqlResult.InvoiceAmount.Value.ToString("N2"),
				InvoiceExpress = sqlResult.InvoiceExpress == null ? string.Empty : sqlResult.InvoiceExpress,
			};

			return JsonCamelCase(Utility.CreateSuccessJsonResult(string.Empty, result),
					JsonRequestBehavior.AllowGet);
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		[Route("SaveInvoiceInfo")]
		public async Task<JsonResult> SaveInvoiceInfo(ConferenceLocaleModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName);

			var result = await DbContext.ConferenceAttendenceInfo
					.FirstOrDefaultAsync(x => x.ID == model.Id);

			if (result == null)
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgRecordNotExist),
						JsonRequestBehavior.AllowGet);
			}

			if (result.HasInvoiced == false)
			{
				result.InvoiceTitle = model.InvoiceTitle;
				result.TaxNum = model.TaxNum;
				result.Bank = model.Bank;
				result.BankAccount = model.BankAccount;
				result.AddressAndTel = model.AddressAndTel;
			}

			result.InvoiceAddress = model.InvoiceAddress;
			result.InvoiceReceive = model.InvoiceReceive;
			result.InvoiceTel = model.InvoiceTel;
			result.InvoiceMail = model.InvoiceMail;

			result.Updater = LoginUser.UserName;
			result.UpdateIP = LoginUser.IP;
			result.UpdateDate = DateTime.Now;

			await DbContext.SaveChangesAsync();

			return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessSubmit),
					JsonRequestBehavior.AllowGet);
		}

		/// <summary>
		/// 支付宝
		/// </summary>
		/// <param name="conferenceId"></param>
		/// <param name="attendenceId"></param>
		/// <returns></returns>
		public async Task<JsonResult> Alipay(string conferenceId, string attendenceId)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName);

			var alipay = await DbContext.AlipayMaster.FirstOrDefaultAsync(x => x.ConferenceId == conferenceId);
			var sysPaymentMaster = await DbContext.SysPaymentMaster.FirstOrDefaultAsync(x => x.PaymentName == ConstValues.PayType.支付宝);
			var conferencePaymentMaster = await DbContext.ConferencePaymentMaster.FirstOrDefaultAsync(x => x.ConferenceId == conferenceId && x.PayId == sysPaymentMaster.ID);

			if (alipay != null && conferencePaymentMaster != null)
			{
				var conferenceMaster = await DbContext.ConferenceMaster.FirstOrDefaultAsync(x => x.ID == conferenceId);
				var conferenceAttendenceInfo = await DbContext.ConferenceAttendenceInfo.FirstOrDefaultAsync(x => x.ID == attendenceId);

				// 支付价格改为从数据库取 zhaoyueqi 2018-06-29
				var fee = conferenceMaster.BenefitStartDate < DateTime.Now && DateTime.Now < conferenceMaster.BenefitEndDate ?
						conferenceAttendenceInfo.Discount.Value.ToString("N2") : conferenceAttendenceInfo.TotalFee.Value.ToString("N2");
				var body = "参会费用共计" + fee + "元";
				fee = fee.Replace(",", string.Empty);

				var subjectBody = DateTime.Now.ToString("yyyy-MM-dd") + "," +
						conferenceMaster.ConferenceNickName + "," +
						conferenceAttendenceInfo.FullName;

				var newID = Utility.GetTableId(ConstValues.TableName.ProfilePaymentRecord);
				var out_trade_no = conferenceId + ConstValues.chrUnderline +
						newID + ConstValues.chrUnderline +
						conferencePaymentMaster.ID.Split(ConstValues.chrHyphen)[2] + ConstValues.chrUnderline +
						Session["ValidateCode"]?.ToString();

				//把请求参数打包成数组
				SortedDictionary<string, string> sParaTemp = new SortedDictionary<string, string>();
				sParaTemp.Add("service", "create_direct_pay_by_user");
				sParaTemp.Add("partner", alipay.Partner);
				sParaTemp.Add("seller_id", alipay.Partner);
				sParaTemp.Add("_input_charset", alipay.InputCharset.ToLower());
				sParaTemp.Add("payment_type", conferencePaymentMaster.ID);
				sParaTemp.Add("notify_url", ConstValues.PayFail);
				sParaTemp.Add("return_url", ConstValues.PaySuccess);
				sParaTemp.Add("subject", subjectBody);
				sParaTemp.Add("out_trade_no", out_trade_no);
				sParaTemp.Add("total_fee", fee);
				sParaTemp.Add("body", body);

				//建立请求
				Dictionary<string, string> dicPara = new Dictionary<string, string>();
				AlipaySubmit sm = new AlipaySubmit(alipay.AlipayKey, alipay.InputCharset, alipay.SignType);
				dicPara = sm.BuildRequestPara(sParaTemp);

				var result = new
				{
					Service = "create_direct_pay_by_user",
					Partner = alipay.Partner,
					Seller_id = alipay.Partner,
					Input_charset = alipay.InputCharset.ToLower(),
					Payment_type = conferencePaymentMaster.ID,
					Notify_url = ConstValues.PayFail,
					Return_url = ConstValues.PaySuccess,
					Sign_type = alipay.SignType,
					Sign = dicPara["sign"].ToString(),
					Subject = subjectBody,
					Out_trade_no = out_trade_no,
					Body = body,
					Fee = fee
				};

				var paymentRecord = new ProfilePaymentRecord
				{
					ID = newID,
					UserName = LoginUser.UserName,
					AttendenceId = attendenceId,
					Fee = double.Parse(fee),
					Currency = conferenceAttendenceInfo.Currency,
					FeeStatus = false,
					Creator = LoginUser.UserName,
					CreateDate = DateTime.Now,
					CreateIP = LoginUser.IP
				};

				DbContext.ProfilePaymentRecord.Add(paymentRecord);
				await DbContext.SaveChangesAsync();

				Session["conferenceId"] = conferenceMaster.ID;
				Session["payId"] = newID;
				Session["payType"] = conferencePaymentMaster.ID;
				Session["actuallyFee"] = fee;
				Session["userName"] = LoginUser.UserName;
				var sysUserMaster = await DbContext.SysUserMaster.FirstOrDefaultAsync(x => x.ID == LoginUser.UserID);
				Session["password"] = StringExtension.Decrypt(sysUserMaster.Password);

				return JsonCamelCase(Utility.CreateSuccessJsonResult(string.Empty, result),
						JsonRequestBehavior.AllowGet);
			}
			else
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgRecordNotExist),
						JsonRequestBehavior.AllowGet);
			}
		}

		/// <summary>
		/// 易支付
		/// </summary>
		/// <param name="conferenceId"></param>
		/// <param name="attendenceId"></param>
		/// <returns></returns>
		public async Task<JsonResult> Epay(string conferenceId, string attendenceId)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName);

			var epay = await DbContext.EpayMaster.FirstOrDefaultAsync(x => x.ConferenceId == conferenceId);

			if (epay != null)
			{
				var sysPaymentMaster = await DbContext.SysPaymentMaster.FirstOrDefaultAsync(x => x.PaymentName == ConstValues.PayType.易支付);
				var conferencePaymentMaster = await DbContext.ConferencePaymentMaster.FirstOrDefaultAsync(x => x.ConferenceId == conferenceId && x.PayId == sysPaymentMaster.ID);
				var conferenceMaster = await DbContext.ConferenceMaster.FirstOrDefaultAsync(x => x.ID == conferenceId);
				var conferenceAttendenceInfo = await DbContext.ConferenceAttendenceInfo.FirstOrDefaultAsync(x => x.ID == attendenceId);

				// 支付价格改为从数据库取 zhaoyueqi 2018-06-29
				var fee = conferenceMaster.BenefitStartDate < DateTime.Now && DateTime.Now < conferenceMaster.BenefitEndDate ?
						conferenceAttendenceInfo.Discount.Value.ToString("N2") : conferenceAttendenceInfo.TotalFee.Value.ToString("N2");
				fee = fee.Replace(",", string.Empty);

				var v_moneytype = string.Empty;
				if (conferenceAttendenceInfo.Currency == ConstValues.Currency.美元)
				{
					v_moneytype = "1";
				}
				else
				{
					v_moneytype = "0";
				}

				var v_language = conferenceMaster.IsInternational ? "en" : "zh";
				var v_oid = DateTime.Now.ToString("yyyyMMdd") + ConstValues.strHyphen + epay.TenantId + ConstValues.strHyphen + DateTime.Now.ToString("yyyyMMddHHmmss");
				var v_url = ConstValues.PaySuccess;
				var key = v_moneytype + epay.CreateDate.Value.ToString("yyyyMMdd") + fee + epay.TenantId + v_oid + epay.TenantId + v_url;
				ClassHmac mac = new ClassHmac();
				var v_md5info = mac.hex_hmac_md5(key, epay.Key);

				var result = new
				{
					TenantId = epay.TenantId,
					TenantAddress = epay.TenantAddress,
					TenantPhone = epay.TenantPhone,
					Postcode = epay.TenantPostcode,
					CreateDate = epay.CreateDate.Value.ToString("yyyyMMdd"),
					v_md5info = v_md5info,
					v_ordername = LoginUser.UserName,
					fee = fee,
					v_oid = v_oid,
					v_url = v_url,
					v_moneytype = v_moneytype,
					v_language = v_language
				};

				var newID = Utility.GetTableId(ConstValues.TableName.ProfilePaymentRecord);
				var paymentRecord = new ProfilePaymentRecord
				{
					ID = newID,
					UserName = LoginUser.UserName,
					AttendenceId = attendenceId,
					Fee = double.Parse(fee),
					Currency = conferenceAttendenceInfo.Currency,
					FeeStatus = false,
					Creator = LoginUser.UserName,
					CreateDate = DateTime.Now,
					CreateIP = LoginUser.IP
				};

				DbContext.ProfilePaymentRecord.Add(paymentRecord);
				await DbContext.SaveChangesAsync();

				Session["conferenceId"] = conferenceMaster.ID;
				Session["payId"] = newID;
				Session["payType"] = conferencePaymentMaster.ID;
				Session["actuallyFee"] = fee;
				Session["userName"] = LoginUser.UserName;
				var sysUserMaster = await DbContext.SysUserMaster.FirstOrDefaultAsync(x => x.ID == LoginUser.UserID);
				Session["password"] = StringExtension.Decrypt(sysUserMaster.Password);

				return JsonCamelCase(Utility.CreateSuccessJsonResult(string.Empty, result),
						JsonRequestBehavior.AllowGet);
			}
			else
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgRecordNotExist),
						JsonRequestBehavior.AllowGet);
			}
		}

		/// <summary>
		/// 贝宝
		/// </summary>
		/// <param name="conferenceId"></param>
		/// <param name="attendenceId"></param>
		/// <returns></returns>
		public async Task<JsonResult> Paypal(string conferenceId, string attendenceId)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName);

			var conferenceMaster = await DbContext.ConferenceMaster.FirstOrDefaultAsync(x => x.ID == conferenceId);
			var conferenceAttendenceInfo = await DbContext.ConferenceAttendenceInfo.FirstOrDefaultAsync(x => x.ID == attendenceId);

			var fee = conferenceMaster.BenefitStartDate < DateTime.Now && DateTime.Now < conferenceMaster.BenefitEndDate ?
					conferenceAttendenceInfo.Discount.Value.ToString("N2") : conferenceAttendenceInfo.TotalFee.Value.ToString("N2");
			fee = fee.Replace(",", string.Empty);

			var item_name = DateTime.Now.ToString("yyyy-MM-dd") + "," +
					conferenceMaster.ConferenceNickName + "," +
					conferenceAttendenceInfo.FullName;

			var newID = Utility.GetTableId(ConstValues.TableName.ProfilePaymentRecord);
			var item_number = newID;

			var result = new
			{
				business = "fxq@sjtusy.com",
				cert_id = "6KQNHHCEMU8QY",
				item_name = item_name,
				item_number = item_number,
				//amount = "0.01",
				amount = fee,
				cancel_return = ConstValues.PayFail,
				notify_url = ConstValues.PaySuccess,
			};

			var paymentRecord = new ProfilePaymentRecord
			{
				ID = newID,
				UserName = LoginUser.UserName,
				AttendenceId = attendenceId,
				Fee = double.Parse(fee),
				Currency = conferenceAttendenceInfo.Currency,
				FeeStatus = false,
				Creator = LoginUser.UserName,
				CreateDate = DateTime.Now,
				CreateIP = LoginUser.IP
			};

			DbContext.ProfilePaymentRecord.Add(paymentRecord);
			await DbContext.SaveChangesAsync();

			Session["conferenceId"] = conferenceMaster.ID;
			Session["payId"] = newID;
			Session["payType"] = "PayPal";
			Session["actuallyFee"] = fee;
			Session["userName"] = LoginUser.UserName;
			var sysUserMaster = await DbContext.SysUserMaster.FirstOrDefaultAsync(x => x.ID == LoginUser.UserID);
			Session["password"] = StringExtension.Decrypt(sysUserMaster.Password);

			return JsonCamelCase(Utility.CreateSuccessJsonResult(string.Empty, result),
					JsonRequestBehavior.AllowGet);
		}
	}
}